<?php
class APIRetriever extends Retriever
{

	protected $retrievedPersonNefubIds = array();
	protected $retrievedTeamGamesNefubIds = array();
	protected $retrievedTeamNefubIds = array();
	protected $retrievedClubNefubIds = array();
	protected $retrievedGameNefubIds = array();
	protected $retrievedLocationNefubIds = array();
	
	protected $addedNefubObjects;
	
	private static $instance;
	/**
	 *
	 * @return APIRetriever
	 */
	public static function getInstance()
	{
		if(null == self::$instance)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	protected function retrievePerson($nefubId)
	{
		$url = NEFUB_API .'/person.php?id='.$nefubId;
		$contents = $this->getNefubContents($url);
		$personDetails = json_decode($contents);				
		$oPerson = self::convertPerson($personDetails);
		
		self::put('Persoon ' . $oPerson->name . ' toegevoegd');

		$oRetrieveLog = $this->retrieveLog;
		
		if(is_array($personDetails->Teams))
		{
			$teams = $personDetails->Teams;
			foreach($teams as $team)
			{
				if(!($oTeam = Team::getByNefubId($team->ID)))
				{
					$oTeam = new Team();
					$oTeam->nefub_id = $team->ID;
					$oTeam->name = $team->Name;
					
					$competition = $team->Competition;
					
					self::put('Team ' . $oTeam->name . ' toevoegen');
					self::put('Team ' . $oTeam->name . ' toevoegen');
					$newTeams++;
					
					if(!($oCompetition = Competition::getByNefubId($competition->ID)))
					{
						$oCompetition = new Competition();
						$oCompetition->name = $competition->Name;
						$oCompetition->nefub_id = $competition->ID;
						$aSeasonYears = explode('-', $competition->Season);
						$oCompetition->season_nefub_id = $aSeasonYears[0];
						$oCompetition->save();								
					}
					
					$oGenre = $this->convertGenre($competition->Genre);
					$oGender = $this->convertGenre($competition->Gender);
					$oCompetitionType = $this->convertCompetitionType($competition->Type);
					
					$oCompetition->genre_id = $oGenre->getId();
					$oCompetition->gender_id = $oGender->getId();
					$oCompetition->competition_type_id = $oCompetitionType->getId();
					$oCompetition->save();
					
					$oTeam->season_nefub_id = $oCompetition->season_nefub_id;
					$oTeam->save();
					self::put('Team ' . $oTeam->name . ' toegevoegd');
					$newTeams++;
				}
				
				if(!$oTeamPerson = TeamPerson::getByNefubId($oPerson->nefub_id, $oTeam->nefub_id))
				{
					$oTeamPerson = new TeamPerson();
					$oTeamPerson->team_nefub_id = $oTeam->nefub_id;
					$oTeamPerson->person_nefub_id = $oPerson->nefub_id;
					$oTeamPerson->save();
					self::put('Persoon ' . $oPerson->name . ' aan team '. $oTeam->name . ' toegevoegd');
					$newTeamPersons++;
				}
			}
		}
		else
		{
		
			self::put("API is aangepast");
			self::put($personDetails);
			$data["msg"] = "Kon geen teams van persoon ophalen. API is aangepast: \n".print_r($personDetails, true);
			$this->updateLog($data, true);
			exit;
		}
		$newData = array
		(
			'teams' => $newTeams,
			'personen' => $newPersons,
			'teampersonen' => $newTeamPersons
		);		
		$this->updateLog($newData);
	}
	
	public function retrieveCompetitions()
	{
		$oSeason = $this->getSeason();
		$this->retrieveLog = new RetrieveLog();
		$this->retrieveLog->start_time = date('Y-m-d H:i:s');
		$this->retrieveLog->type =  'COMPETITION';
		$this->updateLog('Start ophalen competities');
		
		$url = NEFUB_API .'/season.php?id='.$oSeason->nefub_id;
		$season = $this->getNefubContentsParsed($url);
		if(!$oSeason->name)
		{
			$oSeason->name = $season->Name;
			$oSeason->save();
		}
		
		$competitions = $season->Competitions;
		
		foreach($competitions as $competition)
		{	
			if(!Competition::getByNefubId($competition->ID))
			{		
				$url = NEFUB_API .'/competition.php?id='.$competition->ID;
				$competition = $this->getNefubContentsParsed($url);				
				$oCompetition = $this->convertCompetition($competition);			
			}
		}
		$this->updateLog('Ophalen competities voltooid', true, true);	
	}
	
	public function retrieve()
	{
		$this->retrieveLog = new RetrieveLog();
		$this->retrieveLog->start_time = date('Y-m-d H:i:s');
		$this->retrieveLog->type = 'TEAM';
		$this->updateLog("\nStart ophalen poules");
		$this->updatePoules();
		$this->updateLog("\nStart ophalen teams");
		$this->updateTeams();		
		$this->updateLog("\nStart ophalen van ontbrekende personen");
		$this->updateMissingPersons();
		$this->updateLog('Teams ophalen voltooid', true, true);
	}
	
	protected function updatePoules()
	{		
		$aPoules = Poule::getAll(array(), 'competition_nefub_id');		
		foreach ($aPoules as $oPoule)
		{
			$url = NEFUB_API .'/poule.php?id='.$oPoule->nefub_id;
			$poule = $this->getNefubContentsParsed($url);
			$oPouleType = $this->convertPouleType($poule->Type);
			$oPoule->poule_type_id = $oPouleType->getId();			
			$pouleRankings = $poule->Ranking;
			if(is_array($pouleRankings))
			{
				foreach($pouleRankings as $pouleRanking)
				{
					$team = $pouleRanking->Team;
					if(!$oPouleTeam = PouleTeam::getByNefubId($team->ID, $oPoule->nefub_id))
					{
						$oPouleTeam = new PouleTeam();
						$oPouleTeam->team_nefub_id = $team->ID;
						$oPouleTeam->poule_nefub_id = $oPoule->nefub_id;
						self::put('Team '.$team->Name.' aan poule '.$oPoule->name.' toegevoegd');
					}				
					
					$oPouleTeam->ranking = $pouleRanking->Position;
					$oPouleTeam->game_points = $pouleRanking->Points;
					
					$numberOfGames = $pouleRanking->{'Number of Games'};
					$oPouleTeam->games_won = $numberOfGames->Won;
					$oPouleTeam->games_lost = $numberOfGames->Lost;
					$oPouleTeam->games_tied = $numberOfGames->Draw;
					$oPouleTeam->games_played = $numberOfGames->Played;
					
					$numberOfGoals = $pouleRanking->{'Number of Goals'};
					$oPouleTeam->score_total = $numberOfGoals->Difference;
					$oPouleTeam->score_plus = $numberOfGoals->Scored;
					$oPouleTeam->score_minus = $numberOfGoals->Conceded;
					$oPouleTeam->save();
				}
			}
			else
			{
				self::put('Standen voor poule '.$oPoule->name . ' niet gevonden');
			}
			self::put('Statistieken poule '.$oPoule->name.' geupdatet');
		}		
	}
	
	public function updateTeams()
	{
	
		$aPoules = Poule::getAll(array(), 'competition_nefub_id');
				
		
		foreach ($aPoules as $oPoule)
		{
			$aPouleTeams = $oPoule->getPouleTeams();
			
			foreach($aPouleTeams as $oPouleTeam)
			{
				if($this->retrievedTeamNefubIds[$oPouleTeam->team_nefub_id] !== true)
				{	
					$url = NEFUB_API .'/team.php?id='.$oPouleTeam->team_nefub_id;
					$team = $this->getNefubContentsParsed($url);
					
					$oTeam = Team::getByNefubId($team->ID);
					if(!$oTeam)
					{
						$oTeam = new Team();
						$oTeam->nefub_id = $team->ID;
						$oTeam->name = $team->Name;
						$oTeam->competition_nefub_id = $oPoule->competition_nefub_id;
						$oTeam->season_nefub_id = $oPoule->season_nefub_id;				

						if($team->Club)
						{
							$oClub = $this->convertClub($team->Club);
						}
						else
						{
							self::put('Geen club gevonden voor '.$team->Name.': '.$url);
						}
						$oTeam->club_nefub_id = $oClub->nefub_id;
						$oTeam->color_shirt = $team->Dress->Shirt;
						$oTeam->color_shorts = $team->Dress->Short;
						self::put('Team '.$team->Name.' toegevoegd');
					}

					if(is_array($team->Players))
					{
						foreach($team->Players as $teamPlayer)
						{
							$this->convertTeamPerson($teamPlayer, $oTeam);
						}
					}
					else
					{
						self::put('Geen spelers gevonden voor '.$team->Name);						
					}
					$this->retrieveTeamGames($team, 'schedule');
					
					
					$query = "SELECT COUNT(Game.nefub_id) as countGames
								FROM Game
								WHERE
									(team1_nefub_id = '".$team->ID."'
									OR
									team2_nefub_id = '".$team->ID."')
									AND
									Game.date < CURDATE()";
					$rows = Database::select_rows_by_query($query);
					$playedGames = $rows[0]['countGames'];

					$bRetrieveResults = true;
					if($playedGames)
					{
						// Als er geen oude wedstrijden in de DB staan, vermoedelijk zijn ze dan niet eerder opgehaald. 
						$query .= " AND Game.actions_retrieved = 0";
						$rows = Database::select_rows_by_query($query);
						$gamesToRetrieve = $rows[0]['countGames'];
						$bRetrieveResults = $gamesToRetrieve != 0;
					}
					
					if($bRetrieveResults)
					{
						$this->retrieveTeamGames($team, 'results');
					}
					else
					{
						self::put('Resultaten voor '.$oTeam->name.' hoeven niet vernieuwd te worden');
					}
					
					$oTeam->save();
					$this->retrievedTeamNefubIds[$oPouleTeam->team_nefub_id] = true;
				}
			}
		}
		
	}
	
	public function updateMissingPersons()
	{
		$query = "	SELECT DISTINCT(TeamPerson.person_nefub_id)
					FROM TeamPerson
					WHERE TeamPerson.person_nefub_id NOT IN
					(					
						SELECT DISTINCT(Person.nefub_id)
						FROM Person
					)";
		$missingTeamPersons = Database::select_rows_by_query($query);
		self::put(count($missingTeamPersons) .' ontbrekende teamspelers gevonden');
		$query = "	SELECT DISTINCT(GamePerson.person_nefub_id)
					FROM GamePerson
					WHERE GamePerson.person_nefub_id NOT IN
					(					
						SELECT DISTINCT(Person.nefub_id)
						FROM Person
					)";
		$missingGamePersons = Database::select_rows_by_query($query);
		self::put(count($missingGamePersons) .' ontbrekende wedstrijdspelers gevonden');
		
		$missingPersons = array_merge($missingTeamPersons, $missingGamePersons);
		
		foreach ($missingPersons as $missingPerson)
		{
			$nefubId = $missingPerson['person_nefub_id'];
			if($this->retrievedPersonNefubIds[$nefubId] !== true)
			{
				$this->retrievePerson($nefubId);				
				$this->retrievedPersonNefubIds[$nefubId] = true;
			}	
		}
	}
	
	protected function updateLog($data, $finished = false, $success = false)
	{
		$oRetrieveLog = $this->retrieveLog;
		$msFinish = microtime(true);
		$msStart = strtotime($oRetrieveLog->start_time);
		$msTotal = ($msFinish - $msStart) * .001;
		$minutes = floor($msTotal / 60);
		$seconds = $msTotal % 60;
		$print = array('status' => $data);
		
		$print['Clubs'] = count($this->retrievedClubNefubIds);
		$print['Teams'] = count($this->retrievedTeamNefubIds);
		$print['Games'] = count($this->retrievedGameNefubIds);
		$print['Locations'] = count($this->retrievedLocationNefubIds);
		$print['Persons'] = count($this->retrievedPersonNefubIds);
		
		$oRetrieveLog->data = print_r($print, true);
		$oRetrieveLog->requests = $this->countRequests;
		$oRetrieveLog->successfully = (int)$success;
		$oRetrieveLog->finished = (int)$finished;
		$oRetrieveLog->finish_time = date('Y-m-d H:i:s', $msFinish);
		$oRetrieveLog->total_time = $oRetrieveLog->getDuration();		
		$oRetrieveLog->save();
	}
	
	public static function render($url)
	{
		@get_headers($url.'?clear=1') or print('Render mislukt: '.$url.'<br />');
	}
	
	public function clear_renders()
	{				
		$msStart = microtime(true);
		
		$renderDirectory =  'renders/'.$this->season->nefub_id.'/'. date('Y') .'_wk'.date('W');
		recursive_remove_directory($renderDirectory);
		
		// Voorpagina
		self::put('Render voorpagina ');
		self::render(HOST);
		
		// Agenda
		self::put('Render agenda ');
		self::render(HOST.'/agenda');
		
		// Uitslagen
		self::put('Render uitslagen ');
		self::render(HOST.'/uitslagen');
		
		
		$modelRenders = array
		(
			'team' => 'Team',
			'poule' => 'Poule',
			'competitie' => 'Competition',
			'wedstrijd' => 'Game',
			'persoon' => 'Person',
			'locatie' => 'Location'
		);
		
		
		foreach($modelRenders as $name => $class)
		{
			self::put('Render '.$name."pagina's");
			$aModels = Model::getAllModels($class, null, 'nefub_id');
			
			foreach($aModels as $oModel)
			{
				if($oModel->name)
				{
					self::put('Render '.$name."pagina voor ".$oModel->name);					
				}
				else
				{
					self::put('Render '.$name."pagina voor #".$oModel->nefub_id);
				}
				self::render(HOST.'/'.$name.'/'.$oModel->nefub_id);
			}	
		}
		
		$msFinish = microtime(true);
		$msTotal = $msFinish - $msStart;
		
		$minutes = floor($msTotal / 60);
		$seconds = $msTotal % 60;
		
		return 'renders voltooid in '.$minutes.' minuut '.$seconds.' seconden<hr />';
	}
		
	protected function getAPITeamDetails($nefubId)
	{
		return $this->getNefubContentsParsed(NEFUB_API . '/team.php?id='.$nefubId);
	}
	
	protected function getNefubContentsParsed($url)
	{
		$data = $this->getNefubContents($url);
		return json_decode($data);		
	}
	
	/**
	 * 
	 * @param stdClass $club
	 * return Club
	 */
	protected function convertClub(stdClass $club)
	{
		$oClub = Club::getByNefubId($club->ID);
		if(!$oClub)
		{
			$oClub = new Club();
			$oClub->nefub_id = $club->ID;
			$oClub->name = $club->Name;
			$oClub->save();
			$this->addedNefubObject($oClub);
		}
		return $oClub;
	}
	
	/**
	 * 
	 * @param stdClass $team
	 */
	protected function retrieveTeam(stdClass $team)
	{		
		self::put('Haal gegevens van team '.$team->ID . '');
		if($this->retrievedTeamNefubIds[$team->ID] !== true)
		{
			$teamDetails = $this->getNefubContentsParsed(NEFUB_API .'/team.php?id='.$team->ID);
			
			if(!$teamDetails)
			{				
				self::put("Geen contents opgehaald voor team");
				return;
			}
			
			$oTeam = $this->convertTeam($teamDetails, $this->getSeason()->nefub_id);
			self::put('Team '.$team->ID . ' toegevoegd: '.$oTeam->name.'<br />');
			
			$this->retrieveTeamPoules($team, $oTeam);
			$this->retrieveTeamGames($team, 'schedule');
			$this->retrieveTeamGames($team, 'results');
			$this->retrievedTeamNefubIds[$team->ID] = true;				
		}
		else 
		{
			//self::put('Team '.$team->ID . ' is al eerder opgehaald: '.$aTeams[$team->ID]->name.'<br />');
		}	
	}
	
	/**
	 * 
	 * @param stdClass $team
	 * @param string $gamesURL
	 */
	public function retrieveTeamGames(stdClass $team, $gamesURL)
	{
		if(!is_array($this->retrievedTeamGamesNefubIds[$gamesURL]))
		{
			$this->retrievedTeamGamesNefubIds[$gamesURL] = array();
		}		
		
		if($this->retrievedTeamGamesNefubIds[$gamesURL][$team->ID] !== true)
		{
			$url = NEFUB_API .'/'.$gamesURL.'.php?team='.$team->ID;
			$teamGamesDetails = $this->getNefubContentsParsed($url);
							
			if($teamGamesDetails)
			{			
				if(isset($teamGamesDetails->wedstrijden))
				{	
					$teamGames = $teamGamesDetails->wedstrijden;								
				}
				elseif(isset($teamGamesDetails->games))
				{
					$teamGames = $teamGamesDetails->games;
				}
				else
				{
					self::put("Kon team games niet parsen ".$url);
					$this->updateLog('Gecrasht bij parsen van team games '.$url, true);
					exit;
				}
			}
			else
			{
				$this->updateLog('Gecrasht bij contents ophalen van team games '.$url, true);
				exit;
			}
			
			
			if(count($teamGames))
			{
				self::put(count($teamGames) . ' wedstrijden gevonden voor '.$team->Name.' ('.$gamesURL.')');
				foreach($teamGames as $teamGame)
				{
					$this->retrieveGame($teamGame);
				}
				self::put(count($teamGames) . ' wedstrijden toegevoegd voor '.$team->Name);
			}
			else
			{
				self::put('Kon geen wedstrijden vinden in data van '.$url);																				
			}
			
			$this->retrievedTeamGamesNefubIds[$gamesURL][$team->ID] = true;
		}
	}
	
	public function retrieveTeamPoules(stdClass $team, Team $oTeam)
	{
		$poules = $team->Poules;
		
		foreach($poules as $poule)
		{
			$this->convertPouleTeam($poule, $oTeam);	
		}		
	}
	/**
	 * 
	 * @param stdClass $game
	 */
	protected function retrieveGame(stdClass $game)
	{
		if($this->retrievedGameNefubIds[$game->ID] !== true)
		{
			$oGame = $this->convertGame($game);			
			$this->retrievedGameNefubIds[$game->ID] = true;										
		}
		else
		{
			//self::put('Wedstrijd ' . $game->ID . ' is al eerder toegevoegd');
		}		
	}
	
	/**
	 * 
	 * @param Team $oTeam
	 * @param bool $save
	 * @return Game
	 */
	public function getTeamGames(Team $oTeam, $save = true)	
	{
		$aGames = array();
		$url = NEFUB_API .'/games.php?team='.$oTeam->nefub_id;
		
		$json = $this->getNefubContents($url);
		$result = json_decode($json);
		
		if(is_array($result->Games))
		{
			
			foreach($result->Games as $game)
			{
				$oGame = null;
				if(!isset($aGames[$game->ID]))
				{	
					if(!$oGame->locked)
					{
						$oGame = $this->convertGame($game, $oTeam->nefub_id, $oGame, $this->getSeason()->nefub_id);
						if($save)
						{
							$exists = $oGame->exists();
							$oGame->save();				
							if(!$exists)
							{
								self::put("Wedstrijd toegevoegd ". $oGame->team1_nefub_id . " - ". $oGame->team2_nefub_id . " op ".$oGame->date ." om ".$oGame->time);
							}
						}		
					}	
					$aGames[$oGame->nefub_id] = $oGame;
				}
			}
		}
		
		return $aGames;
		
	}
	
	/**
	 * 
	 * @param stdClass $game
	 * @param int $teamNefubId
	 * @param Game $oGame
	 * @return Game
	 */
	protected function convertGame(stdClass $game)
	{		
		if($this->retrievedGameNefubIds[$game->ID])
		{
			return $oGame;
		}
		
		$oGame = Game::getByNefubId($game->ID);
		if(!$oGame)
		{
			$oGame = new Game();
			$oGame->nefub_id = $game->ID;
			$this->addedNefubObject($oGame);									
		}
		
		if($oGame->actions_retrieved == 1)
		{
			return $oGame;
		}
		
		if(count($game->{'Match Officials'}))
		{
			$referees = $game->{'Match Officials'};
			// Backwards compatability
			if($referees[0]->Team)
			{
				$oGame->ref_team_nefub_id = $referees[0]->Team->ID;
			}
			
			foreach($referees as $referee)
			{
				$this->convertReferee($oGame, $referee);
			}
		} 
		
		$oGame->team1_nefub_id = $game->Home->ID;
		$oGame->team2_nefub_id = $game->Away->ID;
		
		$oLocation = $this->retrieveLocation($game->Location->ID);
				
		$oGame->location_nefub_id = $game->Location->ID;
		$oGame->field = $game->Field;
		
		list($gameDay, $gameMonth, $gameYear) = explode('-', $game->Date);
		$oGame->date = $gameYear .'-'.$gameMonth.'-'.$gameDay;
		$oGame->time = $game->Time;
		$oGame->finished = is_object($game->Result);		
		
		$oCompetition = $this->convertCompetition($game->Competition);
		$oGame->competition_nefub_id = $oCompetition->nefub_id;
		$oGame->season_nefub_id = $oCompetition->season_nefub_id;
		
		if($oGame->finished)
		{
			$oGame->team1_score = $game->Result->Home;
			$oGame->team2_score = $game->Result->Away;
			$oGame->team1_shots = $game->Shots->Home;
			$oGame->team2_shots = $game->Shots->Away;
			
			if(!$oGame->actions_retrieved)
			{
				$this->convertGamePersons($game->Formation->Home, $game->Home->ID, $oGame);
				$this->convertGamePersons($game->Formation->Away, $game->Away->ID, $oGame);
				Database::delete_rows('GameAction', array('game_nefub_id' => $oGame->nefub_id));
				$this->convertGameActions($game->Events, $oGame);
				Game::updateActionsRetrieved($oGame);
			}
		}
		$oGame->save();
		$this->retrievedGameNefubIds[$oGame->nefub_id] = $oGame;
		return $oGame;		
	}
	
	/**
	 * 
	 * @param ing $locationNefubId
	 * return Location
	 */
	protected function retrieveLocation($locationNefubId)
	{
		$oLocation = Location::getByNefubId($locationNefubId);
		if(!$oLocation)
		{
			$url = NEFUB_API .'/location.php?id='.$locationNefubId;
			$locationContents = $this->getNefubContents($url);
			$locationData = json_decode($locationContents);
			
			$oLocation = new Location();
			$oLocation->nefub_id = $locationNefubId;			
			$oLocation->name = $locationData->Name;
			$oLocation->street = $locationData->Address;
			$oLocation->postalcode = $locationData->PostalCode;
			$oLocation->city = $locationData->Place;
			$oLocation->telephone = $locationData->Phone;
			$oLocation->website = $locationData->Url;
			$oLocation->email = $locationData->{'E-mail'};
			$oLocation->route = $locationData->Route;
			$oLocation->save();			
			
			$this->addedNefubObject($oLocation);
			self::put('Locatie '.$locationNefubId.' toegevoegd: '.$oLocation->name.' in '. $oLocation->city);			
		}
		return $oLocation;
	}
	
	/**
	 * @param stdClass $competition
	 * 
	 * @return Competition
	 */
	protected function convertCompetition(stdClass $competition)
	{		
		$oCompetition = Competition::getByNefubId($competition->ID);
		if(!$oCompetition)
		{
			$oCompetition = new Competition();
			$oCompetition->name = $competition->Name;
			$oCompetition->nefub_id = $competition->ID;			
			$oCompetition->season_nefub_id = $this->getSeason()->nefub_id;
			self::put('Competitie '.$oCompetition->name.' toegevoegd');
			
			$this->addedNefubObject($oCompetition);
		}
		if($competition->Poules)
		{
			foreach($competition->Poules as $poule)
			{
				$oPoule = Poule::getByNefubId($poule->ID);
				if(!$oPoule)
				{
					$oPoule = new Poule();
					$oPoule->nefub_id = $poule->ID;
					$oPoule->name = $poule->Name;
					$oPoule->competition_nefub_id = $oCompetition->nefub_id;					
					self::put('Poule '.$oPoule->name.' toegevoegd'); 
				}				
				$oPoule->sorting = $poule->Order;
				$oPoule->save();
			}
		}
		$oGender = $this->convertGender($competition->Gender);
		$oGenre = $this->convertGenre($competition->Genre);
		$oCompetitionType = $this->convertCompetitionType($competition->Type);
		
		$oCompetition->gender_id = $oGender->getId();	
		$oCompetition->genre_id = $oGenre->getId();	
		$oCompetition->competition_type_id = $oCompetitionType->getId();	
		$oCompetition->save();
		
		return $oCompetition;
	}
		
	/**
	 * @param string $gender
	 * 
	 * return Gender
	 */
	protected function convertGender($gender)
	{
		$oGender = Gender::getByNefubName($gender);
		if(!$oGender)
		{
			$oGender = new Gender();
			$oGender->name = ucfirst($gender);
			$oGender->nefub_name = $gender;
			$oGender->save();
			self::put('Nieuwe gender '.$oGender->Name.' toegevoegd');
			
			$this->addedNefubObject($oGender);
		}
		return $oGender;
	}
	
	/**
	 * @param string $genre
	 * 
	 * return Genre
	 */
	protected function convertGenre($genre)
	{
		$oGenre = Genre::getByNefubName($genre);
		if(!$oGenre)
		{
			$oGenre = new Genre();
			$oGenre->name = ucfirst($genre);
			$oGenre->nefub_name = $genre;
			$oGenre->save();
			self::put('Nieuw genre '.$oGender->Name.' toegevoegd');
			$this->addedNefubObject($oGenre);
		}
		return $oGenre;
	}
	
	/**
	 * @param string $competitionType
	 * 
	 * return CompetitionType
	 */
	protected function convertCompetitionType($competitionType)
	{
		$oCompetitionType = CompetitionType::getByNefubName($competitionType);
		if(!$oCompetitionType)
		{
			$oCompetitionType = new CompetitionType();
			$oCompetitionType->name = ucfirst($competitionType);
			$oCompetitionType->nefub_name = $competitionType;
			$oCompetitionType->save();			
			self::put('Competitietype '.$oCompetitionType->name.' toegevoegd');
			$this->addedNefubObject($oCompetitionType);
		}
		return $oCompetitionType;
	}
	
	/**
	 * @param string $pouleType
	 * 
	 * return PouleType
	 */
	protected function convertPouleType($pouleType)
	{
		$oPouleType = PouleType::getByNefubName($pouleType);
		if(!$oPouleType)
		{
			$oPouleType = new PouleType();
			$oPouleType->name = ucfirst($pouleType);
			$oPouleType->nefub_name = $pouleType;
			$oPouleType->save();			
			self::put('Pouletype '.$oPouleType->name.' toegevoegd');
			$this->addedNefubObject($oPouleType);
		}
		return $oPouleType;
	}
	/**
	 * @param string $refereeType
	 * @return RefereeType
	 */
	protected function convertRefereeType($refereeType)
	{
		$oRefereeType = RefereeType::getByNefubName($refereeType);
		if(!$oRefereeType)
		{
			$oRefereeType = new RefereeType();
			$oRefereeType->name = ucfirst($refereeType);
			$oRefereeType->nefub_name = $refereeType;
			$oRefereeType->save();			
			self::put('Wedstrijdleidingtype '.$oRefereeType->name.' toegevoegd');
			$this->addedNefubObject($oRefereeType);
		}
		return $oRefereeType;
	}
	
	/**
	 * @param Game $oGame
	 * @param stdClass $referee
	 * @return Referee
	 */
	protected function convertReferee(Game $oGame, $referee)
	{
		$oRefereeType = self::convertRefereeType($referee->Type);			
		$oReferee = Referee::getByGame($oGame, $oRefereeType, (int)$referee->Order);			
		if(!$oReferee)
		{
			$oReferee = new Referee();
			$oReferee->game_nefub_id = $oGame->nefub_id;
			$oReferee->referee_type_id = $oRefereeType->getId();
			$oReferee->sorting = (int)$referee->Order;
		}				
		
		if($referee->Person)
		{
			$oReferee->person_nefub_id = $referee->Person->ID;					
			self::put('Persoon wedstrijdleiding als '.$oRefereeType->name.' toegevoegd');
		}
		elseif($referee->Team)
		{
			$oReferee->team_nefub_id = $referee->Team->ID;
			self::put('Team wedstrijdleiding als '.$oRefereeType->name.' toegevoegd');
		}
		else 
		{
			self::put('Wedstrijdleiding heeft geen team of persoon');
		}		
		$oReferee->save();
		return $oReferee;
	}
	
	
	/**
	 * 
	 * @param array $formation
	 * @param int $teamNefubId
	 * @param Game $oGame
	 * @return GamePerson[]
	 */
	protected function convertGamePersons(array $formation = array(), $teamNefubId, Game $oGame)
	{
		$aGamePersons = array();
		foreach($formation as $gamePerson)
		{
			$aGamePersons[] = $this->convertGamePerson($gamePerson, $teamNefubId, $oGame);
		}
		return $aGamePersons;
	}
	
	/**
	 * 
	 * @param stdClass $gamePerson
	 * @param int $teamNefubId
	 * @param Game $oGame
	 * @return GamePerson
	 */
	protected function convertGamePerson(stdClass $gamePerson, $teamNefubId, Game $oGame)
	{
		if(!($oGamePerson = GamePerson::getByNefubId($gamePerson->Person->ID, $oGame->nefub_id)))
		{
			$oGamePerson = new GamePerson();
			$this->addedNefubObject($oGamePerson);			
		}
		
		$oGamePerson->game_nefub_id = $oGame->nefub_id;
		$oGamePerson->team_nefub_id = $teamNefubId;
		$oGamePerson->person_nefub_id = $gamePerson->Person->ID;
		$oGamePerson->shirt_number = $gamePerson->Number;
		if($gamePerson->Type)
		{
			$oType = $this->convertGamePersonSpecialType($gamePerson->Type);
			//$oGamePerson->special_game_person_type_id = $oType->getId();			
			$oGamePerson->game_person_special_type_id = $oType->getId();			
		}
		$oGamePerson->save();
		return $oGamePerson;
	}
	
	/**
	 * @param string $gamePersonSpecialType
	 * 
	 * @return GamePersonSpecialType
	 */
	protected function convertGamePersonSpecialType($gamePersonSpecialType)
	{
		if(!($oGamePersonSpecialType = GamePersonSpecialType::getByNefubName($gamePersonSpecialType)))
		{
			$oGamePersonSpecialType = new GamePersonSpecialType();
			$oGamePersonSpecialType->name = $gamePersonSpecialType;
			$oGamePersonSpecialType->nefub_name = $gamePersonSpecialType;
			$oGamePersonSpecialType->use = true;
			$oGamePersonSpecialType->save();
			$this->addedNefubObject($oGamePersonSpecialType);				
		}				
		return $oGamePersonSpecialType;
	}
	
	/**
	 * 
	 * @param array $formation
	 * @param Team $oTeam
	 * @param Game $oGame
	 * @return $aGameActions[]
	 */
	public function convertGameActions(array $events = array(), Game $oGame, $deleteFirst = true)
	{
		$aGameActions = array();
		$team1_score = 0;
		$team2_score = 0;
		foreach($events as $gameAction)
		{
			$oGameAction = $this->convertGameAction($gameAction, $oGame, $team1_score, $team2_score);
			$oGameActions[] = $oGameAction;
			// The only way to keep track of the scores is to increment them when a goal is made
			$team1_score = $oGameAction->team1_score;
			$team2_score = $oGameAction->team2_score;
		}
		return $aGameActions;
	}
	
	/**
	 * 
	 * @param stdClass $gameAction
	 * @param Team $oTeam
	 * @param Game $oGame
	 */
	private function convertGameAction(stdClass $gameAction, Game $oGame, $team1_score, $team2_score)
	{
		$oGameAction = new GameAction();		
		$oGameAction->period = $gameAction->Period;
		$oGameAction->time = '00:'.str_pad(str_replace('.', ':', $gameAction->Time), 5, '0', STR_PAD_LEFT);
		$oGameAction->game_nefub_id = $oGame->nefub_id;
	
		
		$oGameAction->team_nefub_id = $gameAction->Team->ID;
		$oGameAction->person_nefub_id = $gameAction->Person->ID;
		if($gameAction->Assist)
		{
			$oGameAction->assist_person_nefub_id = $gameAction->Assist->ID;	
		}
		
		// add new unkown type		
		$oType = GameActionType::getByNefubName($gameAction->Type);
		if(!$oType)
		{
			self::put('Wedstrijdactietype '.$gameAction->Type.'  toegevoegd');
			$oType = new GameActionType();
			$oType->name = $gameAction->Type;
			$oType->nefub_name = $gameAction->Type;
			$oType->use = true;
			$oType->save();
			
			$this->addedNefubObject($oType);
		}		
		$oGameAction->game_action_type_id = $oType->getId();
		
		if($gameAction->Code)
		{
			$oGameAction->code = $gameAction->Code;
			$oGameAction->description = $gameAction->Description;
		}
		
		// add a point to the assigned team is needed
		if($oType->is_goal)
		{
			if($oGameAction->team_nefub_id == $oGame->team1_nefub_id)
			{
				$team1_score++;
			}
			else
			{
				$team2_score++;					
			}
		}
		
		$oGameAction->team1_score = $team1_score;
		$oGameAction->team2_score = $team2_score;
		$oGameAction->save();
		
		$this->addedNefubObject($oGameAction);
		return $oGameAction;
	}

	/**
	 * 
	 * @param stdClass $team
	 * @param int $seasonNefubId
	 * @return Team
	 */
	private function convertTeam(stdClass $team)
	{
		$oTeam = Team::getByNefubID($team->ID);
		if(!$oTeam)
		{
			$oTeam = new Team();
			$oTeam->nefub_id = $team->ID;	
			$this->addedNefubObject($oTeam);	
		}
		$oTeam->name = $team->Name;
		$oTeam->color_shirt = $team->Dress->Shirt;
		$oTeam->color_shorts = $team->Dress->Short;
		if($team->Club instanceof stdClass)
		{
			$oClub = $this->convertClub($team->Club);
			$oTeam->club_nefub_id = $oClub->nefub_id;
		}
		
		$oCompetition = $this->convertCompetition($team->Competition);

		$oTeam->competition_nefub_id = $oCompetition->nefub_id;
		$oTeam->season_nefub_id = $oCompetition->season_nefub_id;
		self::put('Update statistieken van spelers in team '.$oTeam->name);
		foreach($team->Players as $teamPerson)
		{
			$this->convertTeamPerson($teamPerson, $oTeam);
		}
	
		foreach($team->Poules as $pouleTeam)
		{
			$this->convertPouleTeam($pouleTeam, $oTeam);
		}
		$oTeam->save();
		return $oTeam;
	}
	
	/**
	 * 
	 * @param stdClass $teamPerson
	 * @param Team $oTeam
	 */
	private function convertTeamPerson(stdClass $teamPerson, Team $oTeam)
	{
		$oTeamPerson = TeamPerson::getByNefubID($teamPerson->Player->ID, $oTeam->nefub_id);
		if(!$oTeamPerson)
		{			
			$oTeamPerson = new TeamPerson();
			$oTeamPerson->team_nefub_id = $oTeam->nefub_id;
			$oTeamPerson->person_nefub_id = $teamPerson->Player->ID;
			$this->addedNefubObject($oTeamPerson);
			self::put('Speler '.$teamPerson->Player->Name . ' aan team '.$oTeam->name.' toegevoegd');
		}
		else
		{	
			self::put('Update statistieken van speler '.$teamPerson->Player->Name . ' in team '.$oTeam->name);
		}
		$oTeamPerson->shirt_number = $teamPerson->Number;
		$oTeamPerson->games_played = $teamPerson->Statistics->{'Number of Games'};
		$oTeamPerson->goals = $teamPerson->Statistics->Goals;
		$oTeamPerson->assists = $teamPerson->Statistics->Assists;
		$oTeamPerson->penalty_minutes = $teamPerson->Statistics->{'Penalty Time'};
		$oTeamPerson->save();
	}
	
	/**
	 * 
	 * @param Poul $poule
	 * @param Team $oTeam
	 * @return PouleTeam
	 */
	private function convertPouleTeam(stdClass $poule, Team $oTeam)
	{
		$oPoule = Poule::getByNefubID($poule->ID);
		if(!$oPoule)
		{
			$oPoule = new Poule();
			$oPoule->nefub_id = $poule->ID;
			self::put('Fout: poule '.$oPoule->nefub_id .' toegevoegd:'.$oPoule->name.' bij toevoegen van personen');
		}
		$oPoule->name = $poule->Name;

		// copy info from team
		$oPoule->competition_nefub_id = $oTeam->competition_nefub_id;
		$oPoule->season_nefub_id = $oTeam->season_nefub_id;
		$oPoule->save();
		
		$oPouleTeam = PouleTeam::getByNefubID($oTeam->nefub_id, $oPoule->nefub_id);
		if(!$oPouleTeam)
		{
			$oPouleTeam = new PouleTeam();
			$oPouleTeam->poule_nefub_id = $oPoule->nefub_id;
			$oPouleTeam->team_nefub_id = $oTeam->nefub_id;
			$oPouleTeam->save();
			self::put('Team '.$oTeam->nefub_id .':'.$oPoule->name . ' aan poule '.$oPoule->nefub_id .' toegevoegd:'.$oPoule->name);
		}
		return $oPouleTeam;
	}
	
	/**
	 * 
	 * @param stdClass $person
	 * @param Person $oPerson
	 */
	private function convertPerson(stdClass $person, Person $oPerson = null)
	{
		$oPerson = Person::getByNefubId($person->ID);
		if(!$oPerson)
		{
			$oPerson = new Person();
			$oPerson->nefub_id = $person->ID;
		}		
		$oPerson->name = ucfirst($person->Name);
		if($person->Sex == 'Male')
		{
			$oPerson->gender = 'M';			
		}
		elseif($person->Sex == 'Female')
		{
			$oPerson->gender = 'V';			
		}
		
		$oPerson->gender = $person->Sex == 'Male' ? 'M' : 'V';
		$oPerson->save();
		return $oPerson;
	}
	
	private function addedNefubObject(NefubObject $oNefubObject)
	{
		$type = get_class($oNefubObject);
		if(!isset($this->addedNefubObjects[$type]))
		{
			$this->addedNefubObjects[$type] = 1;
		}
		else
		{
			$this->addedNefubObjects[$type]++;			
		}
	}
	
	/**
	 * 
	 */
	public function buildSearchTable()
	{		
		self::put('Zoekresultaten maken');
		
		// Personen		
		$aPersons = Person::getAll();
		$personCount = 0;
		$deletePersonCount = 0;
		foreach($aPersons as $oPerson)
		{
			
			$query = "SELECT DISTINCT(Team.competition_nefub_id), Competition.id
						FROM TeamPerson
						LEFT JOIN Team ON Team.nefub_id = TeamPerson.team_nefub_id
						LEFT JOIN Competition ON Team.competition_nefub_id = Competition.nefub_id
						WHERE TeamPerson.person_nefub_id = '".$oPerson->nefub_id."'
						ORDER BY Team.competition_nefub_id ASC";
			$aCompetitions = Model::getAllFromQuery('Competition', $query);
			$personCompetitions = array();			
			foreach($aCompetitions as $oCompetition)
			{
				if(trim($oCompetition->name))
				{
					$personCompetitions[] = $oCompetition->name;
				}
			}		

			if(count($personCompetitions))
			{
				$oSearchResult = SearchResult::selectByNefubId($oPerson->nefub_id, 'person');
				if(!$oSearchResult)
				{
					$oSearchResult = new SearchResult();
					$oSearchResult->nefub_id = $oPerson->nefub_id;
					$oSearchResult->type = 'person';
					$oSearchResult->url = '/persoon/'.$oPerson->nefub_id;
					$personCount++;
				}
				$oSearchResult->name = $oPerson->name;
				$oSearchResult->subtitle = implode(', ', $personCompetitions);
				$oSearchResult->save();
			}
			else 
			{
				$deletePersonCount += Database::delete_rows('SearchResult', array('nefub_id' => $oPerson->nefub_id, 'type' => 'person'));				
			}
		}
		
		self::put($deletePersonCount .' perso(o)n(en) verwijderd van zoekresultatenlijst');
		self::put($personCount .' perso(o)n(en) toegevoegd aan zoekresultatenlijst');
		// Teams
		$aTeams = Team::getAll();
		$teamCount = 0;
		$deleteTeamCount = 0;
		foreach($aTeams as $oTeam)
		{
			if($oTeam->getCompetition())
			{
				$oSearchResult = SearchResult::selectByNefubId($oTeam->nefub_id, 'team');
				if(!$oSearchResult)
				{
					$oSearchResult = new SearchResult();					
					$oSearchResult->nefub_id = $oTeam->nefub_id;
					$oSearchResult->name = $oTeam->name;
					$oSearchResult->type = 'team';
					$oSearchResult->url = '/team/'.$oTeam->nefub_id;
					$teamCount++;
				}
				$oSearchResult->subtitle = $oTeam->getCompetition()->name;
				$oSearchResult->save();
			}
			else 
			{
				$deleteTeamCount += Database::delete_rows('SearchResult', array('nefub_id' => $oPerson->nefub_id, 'type' => 'team'));				
			}
		}
		self::put($deleteTeamCount .' team(s) verwijderd van zoekresultatenlijst');
		self::put($teamCount .' team(s) toegevoegd aan zoekresultatenlijst');
	}
}
